package ink.tiptop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import ink.tiptop.common.domain.WebworkResponse;
import ink.tiptop.enums.EResp;
import ink.tiptop.persist.domain.bo.JarInfo;
import ink.tiptop.persist.domain.bo.UploadJarsDto;
import ink.tiptop.persist.domain.bo.UploadJarsResultDto;
import ink.tiptop.persist.domain.entity.ZjfModuleLocalEntity;
import ink.tiptop.dto.req.local.module.QueryZjfModuleLocalRequest;
import ink.tiptop.dto.req.remote.publish.PublishRequest;
import ink.tiptop.dto.req.remote.publish.QueryPublishRequest;
import ink.tiptop.configuration.GlobalConfigurationProperties;
import ink.tiptop.common.worker.install.InstallParam;
import ink.tiptop.common.worker.install.InstallResult;
import ink.tiptop.common.worker.install.InstallWorker;
import ink.tiptop.common.domain.rsp.PageResponse;
import ink.tiptop.common.domain.rsp.Response;
import ink.tiptop.service.PublishService;
import ink.tiptop.service.UploadService;
import ink.tiptop.service.ZjfModuleLocalService;
import ink.tiptop.utils.async.executor.Async;
import ink.tiptop.utils.async.wrapper.WorkerWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import ink.tiptop.utils.JSON;
/**
 * 本地模块结构视图(ZjfModuleLocalViewEntity)表服务接口
 *
 * @author makejava
 * @since 2020-06-21 20:39:55
 */
@Service("publishService")
@Slf4j
public class PublishServiceImpl implements PublishService {

    /**
     * 服务对象
     */
    @Resource
    private ZjfModuleLocalService zjfModuleLocalService;
    @Autowired
    private GlobalConfigurationProperties configBean;
    @Autowired
    private UploadService uploadService;

    @Override
    public Response list(QueryPublishRequest request) {
        String name = Optional.ofNullable(request.getSortName()).orElse("NAME");
        request.setSortName(name);
        QueryZjfModuleLocalRequest queryZjfModuleLocalRequest = new QueryZjfModuleLocalRequest();
        BeanUtil.copyProperties(request, queryZjfModuleLocalRequest);
        queryZjfModuleLocalRequest.setIgnore(0);
        return this.zjfModuleLocalService.list(queryZjfModuleLocalRequest);
    }

    @Override
    public Response publish(PublishRequest request) {
        // 1.根据id关联查找本地模块 zjf_module_local, 找到不忽视的
        List<ZjfModuleLocalEntity> listEntity = zjfModuleLocalService.listByIds(request.getId());
        // 2.install到本地
        log.debug("准备install到本地");
        InstallResult result = null;
        try {
            result = installWorker(listEntity);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return WebworkResponse.failed(EResp.EPublish.ERROR_INSTALL_LOCAL);
        }
        log.info("异步install结果:{},打包成功列表:{},打包失败列表:{}", result.getStatus(), JSON.toJSONString(result.getSuccessList()), JSON.toJSONString(result.getFailedList()));
        // 3.只有当打包失败或者打包部分成功的时候,需要返回给前端
        switch (result.getStatus()) {
            case FAILED:
                return WebworkResponse.failed(EResp.EPublish.ERROR_INSTALL_LOCAL);
            case PART_SUCCESS:
                return WebworkResponse.failed(EResp.EPublish.ERROR_INSTALL_PART_SUCCESS);
        }
        // 4.打包都成功了,准备上传到服务器上面,上传工作就交给其他service了
        UploadJarsDto dto = packageDto(listEntity, request.getServerId());
        // 5.响应上传结果...TODO 2020年08月01日22:59:00 zjf
        UploadJarsResultDto response = uploadService.uploadJars(dto);
        if (response.getSuccess()) {
            return new PageResponse<>(response.getResultList()).total(response.getResultList().size()).offset(0);
        }
        return WebworkResponse.ERROR;
    }

    /**
     *  异步install的worker
     *  2020年08月01日22:57:56
     *  zjf
     */
    private InstallResult installWorker(List<ZjfModuleLocalEntity> listEntity) throws Exception {
        // 1.本地路径分隔符
        final String sep = File.separator;
        // 2.映射成worker需要的参数对象
        List<InstallParam> installParams = listEntity.parallelStream().map(a -> {
            InstallParam installParam = new InstallParam();
            installParam.setParent(a.getParent());
            installParam.setName(a.getName());
            installParam.setJar(a.getParent() + sep + a.getName() + a.getOutputTarget() + a.getOutputJar());
            return installParam;
        }).collect(Collectors.toList());
        // 3.创建worker对象
        InstallWorker installWorker = new InstallWorker(configBean.getMavenHome(), configBean.getTarget());
        // 4.组装worker的wrapper
        WorkerWrapper<List<InstallParam>, InstallResult> workerWrapper = new WorkerWrapper.Builder<List<InstallParam>, InstallResult>()
                .worker(installWorker)
                .callback(installWorker)
                .param(installParams)
                .build();
        // 5.启动异步install,超时时间在配置文件中配置
        Async.beginWork(configBean.getInstallTimeout(), workerWrapper);
        // 6.阻塞获取异步install结果
        return workerWrapper.getWorkResult().getResult();
    }

    private UploadJarsDto packageDto(List<ZjfModuleLocalEntity> listEntity, Integer serverId) {
        UploadJarsDto dto = new UploadJarsDto();
        List<JarInfo> jarInfoList = new ArrayList<>();
        JarInfo info = null;
        for (ZjfModuleLocalEntity entity : listEntity) {
            info = new JarInfo();
            BeanUtil.copyProperties(entity, info);
            jarInfoList.add(info);
        }
        dto.setJarInfoList(jarInfoList);
        dto.setServerId(serverId);
        return dto;
    }
}